/**
 * 
 */
package com.shy.base.util;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.apache.commons.lang.StringUtils;
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;

import com.alibaba.fastjson.JSON;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.shy.base.vo.AppConstants;
import com.shy.base.vo.CityCodeVo;
import com.shy.base.vo.WeatherCodeVo;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.Header;
import cn.hutool.http.HttpRequest;
import lombok.extern.slf4j.Slf4j;


@Slf4j
public class WeatherUtil {
	
	public static List<CityCodeVo> cityList = new ArrayList<>();
	public static Map<String, String> cityCodeMap = new HashMap<>();
	public static Map<String, String> cityNameMap = new HashMap<>();
	public static List<WeatherCodeVo> weatherList = new ArrayList<>();
	public static Gson gson = new Gson();
	

	
	static {
		try {
			CacheUtil.clearExpireCache();
			Resource resource = new ClassPathResource("city.json");
			cityList = gson.fromJson(IoUtil.read(resource.getInputStream(), AppConstants.DEFAULT_CHARSET), new TypeToken<List<CityCodeVo>>(){}.getType());
	    	List<CityCodeVo> list = new ArrayList<>();
	    	for (CityCodeVo cityCodeVo : cityList) {
				flatCityList(list, cityCodeVo); 
			}
	    	cityNameMap = list.stream().collect(Collectors.toMap(CityCodeVo::getName, CityCodeVo::getNameen, (v1, v2) -> v1));
	    	cityCodeMap = list.stream().collect(Collectors.toMap(CityCodeVo::getNameen, CityCodeVo::getCode, (v1, v2) -> v1));
			//System.out.println(cityList);
			Resource resource2 = new ClassPathResource("code.json");
			weatherList = gson.fromJson(IoUtil.read(resource2.getInputStream(), AppConstants.DEFAULT_CHARSET), new TypeToken<List<WeatherCodeVo>>(){}.getType());
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	

    /**
     * 获取天气信息
     * @param code
     * @return
     * @author shy
     * @date 2022年7月4日
     */
    public static Map<String, Object> getWeatherByCode(String code) {
    	Map<String, Object> result = new HashMap<>();
        try {
        	String jscode = CacheUtil.get(code);
        	if (StringUtils.isBlank(jscode)) {
        		String url = StrUtil.format(AppConstants.WEATHER_API, code);
                HttpRequest httpRequest = HttpRequest
                        .get(url)
                        .header(Header.REFERER, AppConstants.REFERER_WEATHER)
                        .timeout(10000);
                jscode = httpRequest.execute().body();
                if (jscode.indexOf("cityDZ") >= 0) {
                	CacheUtil.set(code, jscode, DateUtil.toLocalDateTime(DateUtil.offsetMinute(new Date(), 10)));
                }
        	}
        	Map<String, String> dayinfo = CacheUtil.get(code + "_day");
        	if (dayinfo == null || dayinfo.isEmpty()) {
        		dayinfo = get1DWeatherByCode(code);
            	CacheUtil.set(code + "_day", dayinfo, DateUtil.toLocalDateTime(DateUtil.offsetMinute(new Date(), 10)));
        	}
            result.put("fullstring", jscode);
            result.put("cityDZ", gson.fromJson(getCityDz(jscode), Map.class));
            result.put("dataZS", gson.fromJson(getDataZS(jscode), Map.class));
            result.put("alarmDZ", gson.fromJson(getAlarmDZ(jscode), Map.class));
            result.put("dataSK", gson.fromJson(getDataSK(jscode), Map.class));
            result.put("fc", gson.fromJson(getFc(jscode), Map.class));
            result.put("day", dayinfo);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("weather update error:{}", e.getMessage());
        }
        return result;
    }


    /**
     * 获取1天天气信息
     * @param code 代码
     * @return
     * @author shy
     * @date 2022年7月4日
     */
    public static Map<String, String> get1DWeatherByCode(String code) {
    	Map<String, String> result = new HashMap<>();
        try {
            String url = StrUtil.format(AppConstants.WEATHER_API_1D, code);
            HttpRequest httpRequest = HttpRequest
                    .get(url)
                    .header(Header.REFERER, AppConstants.REFERER_WEATHER)
                    .timeout(10000);
            String html = httpRequest.execute().body();
            Document doc = Jsoup.parse(html);
            String sunDown = doc.select(".sun.sunDown span").get(0).text().replace("日落", "").trim();
            String sunUp = doc.select(".sun.sunUp span").get(0).text().replace("日出", "").trim();
            result.put("sunDown", sunDown);
            result.put("sunUp", sunUp);
        } catch (Exception e) {
            log.error("weather update error:{}", e.getMessage());
        }
        return result;
    }

    /**
     * 获取7天天气信息
     * @param code 代码
     * @return
     * @author shycms
     * @date 2022年7月4日
     */
    public static String get7DWeatherByCode(String code) {
        List<Map<String,Object>> list = new ArrayList<>();
        try {
            String url = StrUtil.format(AppConstants.WEATHER_API_7D, code);
            String referer = AppConstants.configMap.get(AppConstants.REFERER_WEATHER);
            Connection.Response res = Jsoup.connect(url).referrer(referer).method(Connection.Method.GET).followRedirects(false).execute();
            Document doc = Jsoup.parse(res.body());
            Elements elements = doc.select(".sky.skyid");
            for (Element element : elements) {
                Map<String,Object> map = new LinkedHashMap<>();
                Elements h1 = element.select("h1");
                Elements wea = element.select("p.wea");
                Elements temH = element.select("p.tem span");
                Elements temD = element.select("p.tem i");
                Elements win1 = element.select("p.win em span:first-child");
                Elements win2 = element.select("p.win em span:last-child");
                Elements winJ = element.select("p.win i");
                Elements bigElements = element.select("big");
                if(bigElements.size() == 2){
                    String imgCodeS = bigElements.get(0).attr("class").replace("png40 ","");
                    String imgCodeX = bigElements.get(1).attr("class").replace("png40 ","");
                    map.put("imgCodeS",imgCodeS);
                    map.put("imgCodeX",imgCodeX);
                }
                if(h1.size()>0){
                    map.put("rq",h1.get(0).text());
                }
                if(wea.size()>0){
                    map.put("wea",wea.get(0).text());
                }
                if(temH.size()>0){
                    map.put("temH",temH.get(0).text());
                }
                if(temD.size()>0){
                    map.put("temD",temD.get(0).text());
                }
                if(win1.size()>0){
                    map.put("win1",win1.get(0).attr("title"));
                }
                if(win2.size()>0){
                    map.put("win2",win2.get(0).attr("title"));
                }
                if(winJ.size()>0){
                    map.put("winJ",winJ.get(0).text());
                }
                list.add(map);
            }
        } catch (Exception e) {
            log.error("weather update error:{}", e.getMessage());
        }
        return JSON.toJSONString(list);
    }
    
    public static String getCityDz(String weather) {
    	String result = null;
    	if (weather.indexOf("cityDZ") >= 0) {
    		result = StrUtil.subBetween(weather, "cityDZ =", ";var");
    	}
    	return result;
    }
    
    public static String getDataZS(String weather) {
    	String result = null;
    	if (weather.indexOf("dataZS") >= 0) {
    		result = StrUtil.subBetween(weather, "dataZS =", ";var");
    	}
    	return result;
    }
    
    public static String getAlarmDZ(String weather) {
    	String result = null;
    	if (weather.indexOf("alarmDZ") >= 0) {
    		result = StrUtil.subBetween(weather, "alarmDZ =", ";var");
    	}
    	return result;
    }
    
    public static String getDataSK(String weather) {
    	String result = null;
    	if (weather.indexOf("dataSK") >= 0) {
    		result = StrUtil.subBetween(weather, "dataSK =", ";var");
    	}
    	return result;
    }
    
    public static String getFc(String weather) {
    	String result = null;
    	if (weather.indexOf("fc =") >= 0) {
    		result = StrUtil.subAfter(weather, "fc =", false);
    	}
    	return result;
    }
    
    private static void flatCityList(List<CityCodeVo> list, CityCodeVo cityCodeVo){
    	if (StringUtils.isNotBlank(cityCodeVo.getCode())) {
    		list.add(cityCodeVo);
    	}
    	if (null != cityCodeVo.getChild()) {
    		for (CityCodeVo child : cityCodeVo.getChild()) {
    			flatCityList(list, child);
			}
    	}
    }


    public static void main(String[] args) throws IOException {
        Connection.Response res = Jsoup.connect("http://www.weather.com.cn/weather/101180101.shtml").referrer("http://www.weather.com.cn/").method(Connection.Method.GET).followRedirects(false).execute();
        //System.out.println(res.body());
        Document doc = Jsoup.parse(res.body());
        Elements elements = doc.select(".sky.skyid");
        List<Map<String,Object>> list = new ArrayList<>();
        for (Element element : elements) {
            Map<String,Object> map = new LinkedHashMap<>();
            Elements h1 = element.select("h1");
            Elements wea = element.select("p.wea");
            Elements temH = element.select("p.tem span");
            Elements temD = element.select("p.tem i");
            Elements win1 = element.select("p.win em span:first-child");
            Elements win2 = element.select("p.win em span:last-child");
            Elements winJ = element.select("p.win i");
            if(h1.size()>0){
                map.put("rq",h1.get(0).text());
            }
            if(wea.size()>0){
                map.put("wea",wea.get(0).text());
            }
            if(temH.size()>0){
                map.put("temH",temH.get(0).text());
            }
            if(temD.size()>0){
                map.put("temD",temD.get(0).text());
            }
            if(win1.size()>0){
                map.put("win1",win1.get(0).attr("title"));
            }
            if(win2.size()>0){
                map.put("win2",win2.get(0).attr("title"));
            }
            if(winJ.size()>0){
                map.put("winJ",winJ.get(0).text());
            }
            list.add(map);
            System.out.println(map);
        }
    }
}